package cn.dansj.configure;

import cn.dansj.bean.CurrentThreadLocalUserInfo;
import cn.dansj.bean.InterfaceConstant;
import cn.dansj.common.request.annotation.permission.Permission;
import cn.dansj.common.request.configure.PermissionFilter;
import cn.dansj.common.utils.enums.BooleanType;
import cn.dansj.common.request.RequestUtils;
import cn.dansj.common.utils.transfer.*;
import cn.dansj.enums.GlobalEnv;
import cn.dansj.utils.project.ProjectUtils;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.*;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.util.List;

/**
 * 拦截请求，检验权限
 */
@Configuration
public class PermissionConfigure implements PermissionFilter {
    @Override
    public List<String> excludePathPatterns() {
        return GlobalEnv.excludePathPatterns;
    }

    @Override
    @SuppressWarnings("all")
    public boolean checkAuth(HttpServletRequest request, Method method, Permission permission, boolean pageNotFound) {
        String controller = method == null ? "" : method.getDeclaringClass().getName();
        // 防止请求没有经过网关直接到后端业务系统
        if (!Transformation.castToBoolean(request.getHeader("x-gateway-dispatch"))) {
            ProjectUtils.recordRequestLog(request, 401, "未过网关的非法请求", controller, false);
            return Transformation.castToBoolean(RequestUtils.response401("非法请求"));
        }
        final String ip = RequestUtils.getRealIp();
        final JSONObject intercept = ProjectUtils.getSettingByRedis("intercept");
        final boolean allowIpNull = intercept.getBooleanValue("allow.ip.null");
        final boolean isBlackList = ArrayUtils.asList(StringUtils.split(Transformation.nvl(intercept.getString("ip.black.list"), ""), ",")).contains(ip);
        boolean isApiPrefix = ProjectUtils.isApiPrefix();

        // 如果是InterfaceBaseRequestURI进入转发api路由的，判断是否有内部转发标识
        if (request.getRequestURI().equals(InterfaceConstant.InterfaceBaseRequestURI)) {
            return RequestUtils.isInternalForward() || Transformation.castToBoolean(RequestUtils.response401("拒绝访问"));
        }
        // 判断ip是否允许为空，获取ip是否在黑名单中
        if ((!allowIpNull && Verification.checkNull(ip)) || isBlackList) {
            ProjectUtils.recordRequestLog(request, 401, "拒绝访问", controller, isApiPrefix);
            return Transformation.castToBoolean(RequestUtils.response401("拒绝访问"));
        }
        CurrentThreadLocalUserInfo.setCurrentThreadLocalUserInfo();
        // 先checkAuth，判断权限和写入接口标识，后续接口权限判断需要用到该标识
        String checkAuth = ProjectUtils.checkAuth();
        // 判断是否权限放行
        if (BooleanType.TRUE.equals(permission.value())) return true;
        //判断除了api接口外的地址是否在地址池中存在
        if (pageNotFound && !isApiPrefix) {
            ProjectUtils.recordRequestLog(request, 404, "路由地址不存在", null, false);
            return Transformation.castToBoolean(RequestUtils.response404());
        }
        // 判断权限返回的错误信息，没有则表示权限验证通过  //调用接口的请求不拦截, 放到HandlerInterceptor里面去处理, 这里不处理转发的dispatch请求
        if (isApiPrefix || Verification.checkNull(checkAuth)) return true;
        // 权限验证失败，返回权限信息
        ProjectUtils.recordRequestLog(request, 401, checkAuth, controller, false);
        return Transformation.castToBoolean(RequestUtils.response401(checkAuth));
    }

    @Override
    public void afterCompletion(ServletRequest servletRequest, ServletResponse servletResponse) {
        CurrentThreadLocalUserInfo.removeCurrentThreadLocalUserInfo();
    }
}
